package com.sky.wsp.mybatis.plus.controller;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.sky.wsp.mybatis.plus.dao.ProjectItemMapper;
import com.sky.wsp.mybatis.plus.dao.entity.ProjectItemEntity;
import com.sky.wsp.mybatis.plus.dao.vo.TaskVO;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.*;

/**
 * @desccription 任务拆分估时-控制器（导出数据后，在Excel里需要手动设置格式、背景色等）
 * @auth wangshaopeng@talkweb.com.cn
 * @date 2023/5/5
 */
@RestController
@RequestMapping("/task")
public class TaskController {
    private static final String[] week = new String[]{"周日", "周一", "周二", "周三", "周四", "周五", "周六"};
    private static final Map<String, String> userMap = new HashMap<>();

    static {
        userMap.put("17822", "姚玲");
        userMap.put("23514", "成峰");
        userMap.put("23812", "彭波");
        userMap.put("23975", "朱智阳");
        userMap.put("23993", "黄涛");
        userMap.put("24001", "丁鹏");
        userMap.put("24027", "李靖");
        userMap.put("24211", "彭亚运");
        userMap.put("24320", "刘进文");
        userMap.put("90528", "张冬林");
    }


    @Resource
    private ProjectItemMapper projectItemMapper;

    @GetMapping(name = "加载数据", value = "/tree")
    public TaskVO data(String sprintId) {
        /**
         * 表头行数据
         */
        TaskVO root = new TaskVO();
        root.setId(sprintId);
        root.setpId("root");
        root.setTitle("工作日");
        root.setValues(new ArrayList<>());
        root.setChildren(new ArrayList<>());

        /**
         * 工作日行数据，和各工作日，有任务的【开发人员数量】统计的行数据
         */
        TaskVO count = new TaskVO();
        count.setId("dayCount");
        count.setpId(root.getId());
        count.setTitle("人数统计");
        count.setValues(new ArrayList<>());
        count.setChildren(new ArrayList<>());
        root.getChildren().add(count);

        if (StrUtil.isBlank(sprintId)) {
            return root;
        }

        // 统计迭代中所有开发者人员
        List<ProjectItemEntity> handlerList = loadHandler(sprintId);
        if (CollectionUtil.isEmpty(handlerList)) {
            return root;
        }
        List<ProjectItemEntity> taskList = loadTask(sprintId);
        Date[] sprintTime = loadSprintTime(taskList);
        createTree(handlerList, taskList, root, count, sprintTime[0], sprintTime[1]);

        // 打印结果
        printWork(root);
        return root;
    }

    /**
     * 查询迭代下任务的起止时间
     *
     * @param taskList
     * @return
     */
    private Date[] loadSprintTime(List<ProjectItemEntity> taskList) {
        Date startTime = new Date();
        Date endTime = startTime;
        if (null == taskList) {
            return new Date[]{startTime, endTime};
        }

        for (ProjectItemEntity task : taskList) {
            if (null != task.getStartTime()) {
                if (DateUtil.compare(startTime, task.getStartTime()) > 0) {
                    startTime = task.getStartTime();
                }
            }
            if (null != task.getEndTime()) {
                if (DateUtil.compare(endTime, task.getEndTime()) < 0) {
                    endTime = task.getEndTime();
                }
            }
        }
        return new Date[]{startTime, endTime};
    }

    /**
     * 查询迭代下有任务的人员列表
     *
     * @param sprintId
     * @return
     */
    private List<ProjectItemEntity> loadHandler(String sprintId) {
        LambdaQueryWrapper<ProjectItemEntity> query = new LambdaQueryWrapper<>();
        query.select(ProjectItemEntity::getHandledBy);
        query.eq(ProjectItemEntity::getSprintId, sprintId);
        query.eq(ProjectItemEntity::getDelFlag, false);
        query.eq(ProjectItemEntity::getLeafFlag, true);
        query.eq(ProjectItemEntity::getItemType, "task");
        query.groupBy(ProjectItemEntity::getHandledBy);
        List<ProjectItemEntity> projectItemEntities = projectItemMapper.selectList(query);
        return projectItemEntities;
    }

    /**
     * 查询迭代下所有叶子节点任务
     *
     * @param sprintId
     * @return
     */
    private List<ProjectItemEntity> loadTask(String sprintId) {
        LambdaQueryWrapper<ProjectItemEntity> query = new LambdaQueryWrapper<>();
        query.select(
                ProjectItemEntity::getItemCode,
                ProjectItemEntity::getTitle,
                ProjectItemEntity::getHandledBy,
                ProjectItemEntity::getStartTime,
                ProjectItemEntity::getEndTime);
        query.eq(ProjectItemEntity::getSprintId, sprintId);
        query.eq(ProjectItemEntity::getDelFlag, false);
        query.eq(ProjectItemEntity::getLeafFlag, true);
        query.eq(ProjectItemEntity::getItemType, "task");
        query.orderByAsc(ProjectItemEntity::getStartTime);
        List<ProjectItemEntity> projectItemEntities = projectItemMapper.selectList(query);
        return projectItemEntities;
    }

    /**
     * 将所有的叶子节点任务，按开发人（任务行），任务估时（工作日列）进行分组，并组织成树
     *
     * @param handlerList
     * @param taskList
     * @param root
     * @param count
     * @param sprintBeginDate
     * @param sprintEndDate
     */
    private void createTree(
            List<ProjectItemEntity> handlerList,
            List<ProjectItemEntity> taskList,
            TaskVO root,
            TaskVO count,
            Date sprintBeginDate,
            Date sprintEndDate
    ) {
        // 日期：用户集合
        Map<String, Set<String>> usernameMap = new HashMap<>();

        for (ProjectItemEntity user : handlerList) {
            String username = user.getHandledBy();

            /**
             * 当前开发人员，在各工作日的任务数量小计
             */
            TaskVO userCount = new TaskVO();
            userCount.setId(username);
            userCount.setpId(count.getId());
            userCount.setTitle(userMap.get(username));
            userCount.setValues(new ArrayList<>());
            userCount.setChildren(new ArrayList<>());
            count.getChildren().add(userCount);

            for (ProjectItemEntity task : taskList) {
                // 过滤出出当前开发人员的所有任务
                if (!task.getHandledBy().equals(username)) {
                    continue;
                }

                /**
                 * 当前开发人员，当前开发任务，对任务估时跨越的工作日，进行标记
                 */
                TaskVO taskCount = new TaskVO();
                taskCount.setId(task.getItemCode());
                taskCount.setpId(userCount.getId());
                taskCount.setTitle(task.getTitle());
                taskCount.setValues(new ArrayList<>());
                userCount.getChildren().add(taskCount);

                // 处理未估时的任务
                handleTask(root, count, usernameMap, userCount, taskCount, null, task, username);

                Calendar instance = Calendar.getInstance();
                instance.setTime(sprintBeginDate);
                int compare;
                do {
                    handleTask(root, count, usernameMap, userCount, taskCount, instance, task, username);
                    // 工作日加1，继续查询下一个工作日数据
                    instance.add(Calendar.DATE, 1);
                    Date workDay = instance.getTime();
                    compare = DateUtil.compare(workDay, sprintEndDate);
                } while (compare < 1);
            }
        }
    }

    /**
     * 将一条任务，按任务估时，对工作日进行标记
     *
     * @param root
     * @param count
     * @param usernameMap
     * @param userCount
     * @param taskCount
     * @param instance
     * @param task
     * @param username
     */
    private void handleTask(
            TaskVO root,
            TaskVO count,
            Map<String, Set<String>> usernameMap,
            TaskVO userCount,
            TaskVO taskCount,
            Calendar instance,
            ProjectItemEntity task,
            String username
    ) {
        int idx = taskCount.getValues().size();
        Date workDay;
        String dateStr;
        String workDayStr;
        if (null == instance) {
            workDay = null;
            dateStr = "未估时任务";
            workDayStr = "未估时任务";
        } else {
            workDay = instance.getTime();
            dateStr = DateUtil.formatDate(workDay);
            int dayOfWeek = instance.get(Calendar.DAY_OF_WEEK);
            workDayStr = dateStr + week[dayOfWeek - 1];
        }
        Set<String> usernameSet = usernameMap.get(dateStr);
        if (null == usernameSet) {
            usernameSet = new HashSet<>();
            usernameMap.put(dateStr, usernameSet);
        }

        // 添加一个新的工作日列
        if (root.getValues().size() == idx) {
            root.getValues().add(workDayStr);
        }

        // 添加一个新的工作日【有任务的开发人员人数】统计列
        if (count.getValues().size() == idx) {
            count.getValues().add("0");
        }

        // 添加一个当前开发人员在当前工作日的任务数量小计列
        if (userCount.getValues().size() == idx) {
            userCount.getValues().add("0");
        }

        if (null == instance) {
            // 记录未估时任务
            if (null == task.getStartTime() || null == task.getEndTime()) {
                // 任务未估时
                taskCount.getValues().add("1");
                String newUserValue = Integer.parseInt(userCount.getValues().get(idx)) + 1 + "";
                userCount.getValues().set(idx, newUserValue);
                usernameSet.add(username);
            } else {
                // 任务估时了，等待下次循环
                taskCount.getValues().add("0");
            }
        } else {
            // 任务估时了
            if (DateUtil.compare(workDay, task.getStartTime()) > -1 && DateUtil.compare(workDay, task.getEndTime()) < 1) {
                // 当前工作日在估时区域内，进行标1操作
                taskCount.getValues().add("1");
                String newUserValue = Integer.parseInt(userCount.getValues().get(idx)) + 1 + "";
                userCount.getValues().set(idx, newUserValue);
                usernameSet.add(username);
            } else {
                // 当前工作日不在估时区域内，进行标0操作
                taskCount.getValues().add("0");
            }
        }
        count.getValues().set(idx, usernameSet.size() + "");
    }

    /**
     * 打印数据
     *
     * @param root
     */
    private void printWork(TaskVO root) {
        System.out.print(root.getId() + "\t" + root.getpId() + "\t" + root.getTitle() + "\t");
        for (String v : root.getValues()) {
            if ("0".equals(v)) {
                System.out.print(" \t");
            } else {
                System.out.print(v + "\t");
            }
        }
        System.out.println();
        List<TaskVO> children = root.getChildren();
        if (null != children) {
            for (TaskVO t : children) {
                printWork(t);
            }
        }
    }
}
